# GNAFU - "Ground, Navy and Air Fuck-Up" real-time strategy game
# Copyright (C) 2008-2009 k0wax <k0waxk0wax@gmail.com>
#
# This file is part of GNAFU.
#
# GNAFU is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GNAFU is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNAFU.  If not, see <http://www.gnu.org/licenses/>.

"""Base unit's module"""
from __future__ import division, absolute_import
from random import randint
import pyglet
from src import vars, geom, entity, sprite, conf, xtypes
from src import game
from src.gamectl import UnitController
from src.consts import *

# enumerate types
unittypes = xtypes.enumtype('UnitTypes', 'ship submarine tank')

class BaseUnitModel(entity.Entity):
    """BaseModel for all units
    Internal models logic starts with '_'"""
    _ctl = UnitController()
    def __init__(self, cx=0, cy=0):
        super(BaseUnitModel, self).__init__()
        self.x = cx * vars.tile_size
        self.y = cy * vars.tile_size
        self.path = []
        self.cx, self.cy = cx, cy
        self.target = None
        self.components = []
        return self._ctl.dispatch_event('on_unit_create', self)
    def __unicode__(self):
        return '<BaseUnit: cx=%d, cy=%d, x=%.2f, y=%.2f>' % (self.cx, self.cy, self.x, self.y)
    def _handle_path(self):
        if self.locked or self.path == []: return
        n = self.path.pop()
        print 'handled', n,
        dir = geom.dir_between(self.cx, self.cy, n.x, n.y)
        print 'dir', dir
        self._step(dir)
    def _handle_moving(self, dt):
        oldx, oldy = self.x, self.y
        self.x += self.dx * dt
        self.y += self.dy * dt
        x_reached = (self.x >= self.dst_x) if self.dst_x > oldx else (self.x <= self.dst_x)
        y_reached = (self.y >= self.dst_y) if self.dst_y > oldy else (self.y <= self.dst_y)
        #print 'x', x_reached, self.dst_x, self.x, self.dst_x > self.x
        if x_reached:
            self.dx = 0
            self.x = self.dst_x
            self.moving_lock = False
            self.dst_x = None
        if y_reached:
            self.dy = 0
            self.y = self.dst_y
            self.moving_lock = False
            self.dst_y = None
        if self.moving_lock == False:
            self.locked = False
    def _update_target(self, dt, target):
        self.set_target(target)
    def update(self, dt):
        super(BaseUnitModel, self).update(dt)
        if self.dir_lock == True:
            pass
        elif self.moving_lock == True:
            self._handle_moving(dt)
        self._handle_path()
        for o in self.components:
            o.update(dt)
    def _step(self, newdir=None):
        if self.locked: return
        print self.dir, 'NEW DIR', newdir
        self.locked = True
        self.moving_lock = True
        dir = self.dir if newdir == None else newdir
        # fixme
        # unset old unit
        #g_field.cells[self.cx][self.cy].unit = False
        k = geom.get_k_by_dir(dir)
        self.cx = (self.cx + k[0]) % game.field.w # fixme
        self.cy = (self.cy + k[1]) % game.field.h
        # set new unit 
        #g_.field.cells[self.cx][self.cy].unit = True
        print 'XXX', self.cx, self.cy, dir
        if newdir != None and newdir != self.dir:
            self.dst_dir = newdir
            print 'set new dst dir'
        else:
            try:
                print 'ROT FINISHED FOR', self.object_name
            except: pass
        if dir in (DIR_N, DIR_NE, DIR_NW):
            self.dst_y = self.y + TILE_SIZE
            self.dy = self.max_speed
        if dir in (DIR_E, DIR_NE, DIR_SE):
            self.dst_x = self.x + TILE_SIZE
            self.dx = self.max_speed
        if dir in (DIR_W, DIR_NW, DIR_SW):
            self.dst_x = self.x - TILE_SIZE
            self.dx = -self.max_speed
        if dir in (DIR_S, DIR_SE, DIR_SW):
            self.dst_y = self.y - TILE_SIZE
            self.dy = -self.max_speed 
    def set_target(self, target, dt=None):
        """controller function"""
        self.target = target
        for o in self.components:
            o.target = target 
            #print 'target set for', o, 'component'
        pyglet.clock.schedule_once(self._update_target, 1.0, target)
        return self._ctl.dispatch_event('on_unit_set_target', self)
    def unset_target(self):
        """controller function"""
        raise NotImplementedError
    def destroy(self):
        """controller function"""
        # Do nothing
        return self._ctl.dispatch_event('on_unit_destroy', self)
    def kill(self):
        """controller function"""
        return self._ctl.dispatch_event('on_unit_kill', self)

class BaseUnit(UnitController, BaseUnitModel):
    pass
